/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package demochess;

import java.awt.Color;
import java.util.ArrayList;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;

/**
 *
 * @author Nhattruong
 */
public class CellRecommender {

    private JButton[][] _chessTable;
    public final Icon bPawn = new ImageIcon(getClass().getResource("/icon/chess-pawn-icon b.png"));
    public final Icon wPawn = new ImageIcon(getClass().getResource("/icon/chess-pawn-icon w.png"));
    public final Icon bRook = new ImageIcon(getClass().getResource("/icon/chess-rook-icon b.png"));
    public final Icon wRook = new ImageIcon(getClass().getResource("/icon/chess-rook-icon w.png"));
    public final Icon bKnight = new ImageIcon(getClass().getResource("/icon/chess-knight-icon b.png"));
    public final Icon wKnight = new ImageIcon(getClass().getResource("/icon/chess-knight-icon w.png"));
    public final Icon bBishop = new ImageIcon(getClass().getResource("/icon/chess-bishop-icon b.png"));
    public final Icon wBishop = new ImageIcon(getClass().getResource("/icon/chess-bishop-icon w.png"));
    public final Icon bKing = new ImageIcon(getClass().getResource("/icon/chess-king-icon b.png"));
    public final Icon wKing = new ImageIcon(getClass().getResource("/icon/chess-king-icon w.png"));
    public final Icon bQueen = new ImageIcon(getClass().getResource("/icon/chess-queen-icon b.png"));
    public final Icon wQueen = new ImageIcon(getClass().getResource("/icon/chess-queen-icon w.png"));
    public final Color HIGHLIGHTCOLOR = new Color(146, 213, 252);
    private boolean _canCastlingShort = true;
    private boolean _canCastlingLong = false;

    public CellRecommender(JButton[][] chessTatble) {
        this._chessTable = chessTatble;
    }

    public void resetTable() {
        _canCastlingLong = true;
        _canCastlingShort = true;
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                setCellBackground(i, j);
                if (i == 1) {
                    _chessTable[i][j].setIcon(bPawn);
                } else {
                    if (i == 6) {
                        _chessTable[i][j].setIcon(wPawn);
                    } else {
                        _chessTable[i][j].setIcon(null);
                    }
                }
            }
        }
        _chessTable[0][0].setIcon(bRook);
        _chessTable[0][7].setIcon(bRook);
        _chessTable[7][0].setIcon(wRook);
        _chessTable[7][7].setIcon(wRook);
        _chessTable[0][1].setIcon(bKnight);
        _chessTable[0][6].setIcon(bKnight);
        _chessTable[7][1].setIcon(wKnight);
        _chessTable[7][6].setIcon(wKnight);
        _chessTable[0][2].setIcon(bBishop);
        _chessTable[0][5].setIcon(bBishop);
        _chessTable[7][2].setIcon(wBishop);
        _chessTable[7][5].setIcon(wBishop);
        _chessTable[0][3].setIcon(bKing);
        _chessTable[0][4].setIcon(bQueen);
        _chessTable[7][3].setIcon(wQueen);
        _chessTable[7][4].setIcon(wKing);
    }

    /**
     * Scan winner
     * @return
     * 0 - there no winner
     * 1 - white win
     * 2 - black win
     * 3 - draw
     */
    public int scanWinner() {
        int rs = 0;
        boolean hasBlackKing = false, hasWhiteKinh = false;
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                if (_chessTable[i][j].getIcon() == bKing) {
                    hasBlackKing = true;
                    continue;
                }
                if (_chessTable[i][j].getIcon() == wKing) {
                    hasWhiteKinh = true;
                    continue;
                }
            }
        }
        if (!hasWhiteKinh || !hasBlackKing) {
            return hasBlackKing ? 1 : 2;
        }
        return rs;
    }

    public boolean makeRecommend(int x, int y) {
        if (_chessTable[7][0].getIcon() != wRook || _chessTable[7][4].getIcon() != wKing) {
            _canCastlingLong = false;
        }
        if (_chessTable[7][7].getIcon() != wRook || _chessTable[7][4].getIcon() != wKing) {
            _canCastlingShort = false;
        }
        ArrayList<Integer> list = new ArrayList<Integer>();
        highlightCell(_chessTable[x][y]);
        if (_chessTable[x][y].getIcon() == wPawn) {
            list.addAll(pawnRecommend(x, y));
            highlightCell(list);
            return true;
        }
        if (_chessTable[x][y].getIcon() == wBishop) {
            list.addAll(bishopRecommend(x, y));
            highlightCell(list);
            return true;
        }
        if (_chessTable[x][y].getIcon() == wKing) {
            list.addAll(kingRecommend(x, y));
            list.addAll(castlingRecommend(x, y));
            highlightCell(list);
            return true;
        }
        if (_chessTable[x][y].getIcon() == wKnight) {
            list.addAll(knightRecommend(x, y));
            highlightCell(list);
            return true;
        }
        if (_chessTable[x][y].getIcon() == wRook) {
            list.addAll(rookRecommend(x, y));
            list.addAll(castlingRecommend(x, y));
            highlightCell(list);
            return true;
        }
        if (_chessTable[x][y].getIcon() == wQueen) {
            list.addAll(rookRecommend(x, y));
            list.addAll(bishopRecommend(x, y));
            highlightCell(list);
            return true;
        }
        setCellBackground(x, y);
        return false;
    }

    private ArrayList<Integer> pawnRecommend(int x, int y) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        if (x == 6 && _chessTable[x - 2][y].getIcon() == null) {
            result.add((x - 2) * 8 + y);
        }
        if (x > 0 && _chessTable[x - 1][y].getIcon() == null) {
            result.add((x - 1) * 8 + y);
        }
        if (x > 0 && y > 0 && isWhiteChess(_chessTable[x - 1][y - 1].getIcon()) == 2) {
            result.add((x - 1) * 8 + y - 1);
        }
        if (x > 0 && y < 7 && isWhiteChess(_chessTable[x - 1][y + 1].getIcon()) == 2) {
            result.add((x - 1) * 8 + y + 1);
        }
        return result;
    }

    private ArrayList<Integer> rookRecommend(int x, int y) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        boolean stopD = false, stopR = false, stopL = false, stopU = false;
        for (int i = x + 1; i <= 7 && !stopD; i++) {
            int status = isWhiteChess(_chessTable[i][y].getIcon());
            if (status == 1) {
                stopD = true;
            } else {
                result.add((i) * 8 + y);
                stopD = status == 2;
            }
        }
        for (int i = x - 1; i >= 0 && !stopU; i--) {
            int status = isWhiteChess(_chessTable[i][y].getIcon());
            if (status == 1) {
                stopU = true;
            } else {
                result.add((i) * 8 + y);
                stopU = status == 2;
            }
        }
        for (int i = y + 1; i <= 7 && !stopR; i++) {
            int status = isWhiteChess(_chessTable[x][i].getIcon());
            if (status == 1) {
                stopR = true;
            } else {
                result.add((x) * 8 + i);
                stopR = status == 2;
            }
        }
        for (int i = y - 1; i >= 0 && !stopL; i--) {
            int status = isWhiteChess(_chessTable[x][i].getIcon());
            if (status == 1) {
                stopL = true;
            } else {
                result.add((x) * 8 + i);
                stopL = status == 2;
            }
        }
        return result;
    }

    private ArrayList<Integer> kingRecommend(int x, int y) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        if (x > 0 && isWhiteChess(_chessTable[x - 1][y].getIcon()) != 1) {
            result.add((x - 1) * 8 + y);
        }
        if (x > 0 && y > 0 && isWhiteChess(_chessTable[x - 1][y - 1].getIcon()) != 1) {
            result.add((x - 1) * 8 + y - 1);
        }
        if (x > 0 && y < 7 && isWhiteChess(_chessTable[x - 1][y + 1].getIcon()) != 1) {
            result.add((x - 1) * 8 + y + 1);
        }
        if (x < 7 && isWhiteChess(_chessTable[x + 1][y].getIcon()) != 1) {
            result.add((x + 1) * 8 + y);
        }
        if (x < 7 && y > 0 && isWhiteChess(_chessTable[x + 1][y - 1].getIcon()) != 1) {
            result.add((x + 1) * 8 + y - 1);
        }
        if (x < 7 && y < 7 && isWhiteChess(_chessTable[x + 1][y + 1].getIcon()) != 1) {
            result.add((x + 1) * 8 + y + 1);
        }
        if (y > 0 && isWhiteChess(_chessTable[x][y - 1].getIcon()) != 1) {
            result.add((x) * 8 + y - 1);
        }
        if (y < 7 && isWhiteChess(_chessTable[x][y + 1].getIcon()) != 1) {
            result.add((x) * 8 + y + 1);
        }
        return result;
    }

    private ArrayList<Integer> castlingRecommend(int x, int y) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        if (y == 0 || y == 7) {
            if (_canCastlingLong && y == 0 && _chessTable[7][1].getIcon() == null
                    && _chessTable[7][2].getIcon() == null && _chessTable[7][3].getIcon() == null) {
                if (!checkWhileChessingCell(7, 2)) {
                    result.add((7) * 8 + 4);
                }
            }
            if (_canCastlingShort && y == 7 && _chessTable[7][6].getIcon() == null
                    && _chessTable[7][5].getIcon() == null) {
                if (!checkWhileChessingCell(7, 6)) {
                    result.add((7) * 8 + 4);
                }
            }
        } else {
            if (_canCastlingLong && _chessTable[7][1].getIcon() == null
                    && _chessTable[7][2].getIcon() == null && _chessTable[7][3].getIcon() == null) {
                if (!checkWhileChessingCell(7, 2)) {
                    result.add((7) * 8);
                }
            }
            if (_canCastlingShort && _chessTable[7][6].getIcon() == null
                    && _chessTable[7][5].getIcon() == null) {
                if (!checkWhileChessingCell(7, 2)) {
                    result.add((7) * 8 + 7);
                }
            }
        }
        return result;
    }

    private ArrayList<Integer> knightRecommend(int x, int y) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        if (x > 1 && y < 7 && isWhiteChess(_chessTable[x - 2][y + 1].getIcon()) != 1) {
            result.add((x - 2) * 8 + y + 1);
        }
        if (x > 0 && y < 6 && isWhiteChess(_chessTable[x - 1][y + 2].getIcon()) != 1) {
            result.add((x - 1) * 8 + y + 2);
        }
        if (x < 7 && y < 6 && isWhiteChess(_chessTable[x + 1][y + 2].getIcon()) != 1) {
            result.add((x + 1) * 8 + y + 2);
        }
        if (x < 6 && y < 7 && isWhiteChess(_chessTable[x + 2][y + 1].getIcon()) != 1) {
            result.add((x + 2) * 8 + y + 1);
        }
        if (x < 6 && y > 0 && isWhiteChess(_chessTable[x + 2][y - 1].getIcon()) != 1) {
            result.add((x + 2) * 8 + y - 1);
        }
        if (x < 7 && y > 1 && isWhiteChess(_chessTable[x + 1][y - 2].getIcon()) != 1) {
            result.add((x + 1) * 8 + y - 2);
        }
        if (x > 0 && y > 1 && isWhiteChess(_chessTable[x - 1][y - 2].getIcon()) != 1) {
            result.add((x - 1) * 8 + y - 2);
        }
        if (x > 1 && y > 0 && isWhiteChess(_chessTable[x - 2][y - 1].getIcon()) != 1) {
            result.add((x - 2) * 8 + y - 1);
        }
        return result;
    }

    private ArrayList<Integer> bishopRecommend(int x, int y) {
        ArrayList<Integer> result = new ArrayList<Integer>();
        boolean stopDL = false, stopDR = false, stopUL = false, stopUR = false;
        for (int i = x + 1; i < 7 && (!stopDL || !stopDR); i++) {
            if ((y + i - x) <= 7 && !stopDR) {
                int status = isWhiteChess(_chessTable[i][y + i - x].getIcon());
                if (status == 1) {
                    stopDR = true;
                } else {
                    result.add(i * 8 + y + i - x);
                    stopDR = status == 2;
                }
            }
            if ((y - i + x) >= 0 && !stopDL) {
                int status = isWhiteChess(_chessTable[i][y - i + x].getIcon());
                if (status == 1) {
                    stopDL = true;
                } else {
                    result.add(i * 8 + y - i + x);
                    stopDL = status == 2;
                }
            }
        }
        for (int i = x - 1; i > 0 && (!stopUL || !stopUR); i--) {
            if ((y + i - x) >= 0 && !stopUR) {
                int status = isWhiteChess(_chessTable[i][y + i - x].getIcon());
                if (status == 1) {
                    stopUR = true;
                } else {
                    result.add(i * 8 + y + i - x);
                    stopUR = status == 2;
                }
            }
            if ((y - i + x) <= 7 && !stopUL) {
                int status = isWhiteChess(_chessTable[i][y - i + x].getIcon());
                if (status == 1) {
                    stopUL = true;
                } else {
                    result.add(i * 8 + y - i + x);
                    stopUL = status == 2;
                }
            }
        }
        return result;
    }

    public boolean checkCastlingMove(int from, int to) {
        int xFrom = from / 8,
                xTo = to / 8,
                yFrom = from % 8,
                yTo = to % 8;
        if (_chessTable[xFrom][yFrom].getIcon() == bKing && _chessTable[xTo][yTo].getIcon() == bRook) {
            return true;
        }
        if (_chessTable[xFrom][yFrom].getIcon() == bRook && _chessTable[xTo][yTo].getIcon() == bKing) {
            return true;
        }
        if (_chessTable[xFrom][yFrom].getIcon() == wKing && _chessTable[xTo][yTo].getIcon() == wRook) {
            return true;
        }
        if (_chessTable[xFrom][yFrom].getIcon() == wRook && _chessTable[xTo][yTo].getIcon() == wKing) {
            return true;
        }
        return false;
    }

    private void highlightCell(JButton jButton) {
        jButton.setBackground(HIGHLIGHTCOLOR);
    }

    private void highlightCell(ArrayList<Integer> list) {
        for (int i = 0; i < list.size(); i++) {
            _chessTable[list.get(i) / 8][list.get(i) % 8].setBackground(HIGHLIGHTCOLOR);
        }
    }

    public void cleanHighlight() {
        for (int i = 0; i < 8; i++) {
            for (int j = 0; j < 8; j++) {
                setCellBackground(i, j);
            }
        }
    }

    private void setCellBackground(int i, int j) {
        if (i % 2 == 0) {
            if (j % 2 == 0) {
                _chessTable[i][j].setBackground(new Color(255, 255, 255));
            } else {
                _chessTable[i][j].setBackground(new Color(114, 114, 114));
            }
        } else {
            if (j % 2 != 0) {
                _chessTable[i][j].setBackground(new Color(255, 255, 255));
            } else {
                _chessTable[i][j].setBackground(new Color(114, 114, 114));
            }
        }
    }

    private int isWhiteChess(Icon icon) {
        if (icon == null) {
            return 0;
        }
        if (icon == wBishop || icon == wKing || icon == wKnight
                || icon == wPawn || icon == wQueen || icon == wRook) {
            return 1;
        }
        return 2;
    }

    private int isBlackChess(Icon icon) {
        if (icon == null) {
            return 0;
        }
        if (icon == bBishop || icon == bKing || icon == bKnight
                || icon == bPawn || icon == bQueen || icon == bRook) {
            return 1;
        }
        return 2;
    }

    public boolean checkWhiteUpLevelMove(int from, int to) {
        int xFrom = from / 8,
                xTo = to / 8,
                yFrom = from % 8,
                yTo = to % 8;
        if (xFrom == 1 && xTo == 0 && _chessTable[xFrom][yFrom].getIcon() == wPawn) {
            return true;
        }
        return false;
    }

    public void upLevelPawn(int from, int to, int chess) {
        int xFrom = from / 8,
                xTo = to / 8,
                yFrom = from % 8,
                yTo = to % 8;
        switch (chess) {
            case 0:
                if (_chessTable[xFrom][yFrom].getIcon() == wPawn) {
                    _chessTable[xTo][yTo].setIcon(wQueen);
                } else {
                    _chessTable[xTo][yTo].setIcon(bQueen);
                }
                _chessTable[xFrom][yFrom].setIcon(null);
                break;
            case 1:
                if (_chessTable[xFrom][yFrom].getIcon() == wPawn) {
                    _chessTable[xTo][yTo].setIcon(wRook);
                } else {
                    _chessTable[xTo][yTo].setIcon(bRook);
                }
                _chessTable[xFrom][yFrom].setIcon(null);
                break;
            case 2:
                if (_chessTable[xFrom][yFrom].getIcon() == wPawn) {
                    _chessTable[xTo][yTo].setIcon(wBishop);
                } else {
                    _chessTable[xTo][yTo].setIcon(bBishop);
                }
                _chessTable[xFrom][yFrom].setIcon(null);
                break;
            case 3:
                if (_chessTable[xFrom][yFrom].getIcon() == wPawn) {
                    _chessTable[xTo][yTo].setIcon(wKnight);
                } else {
                    _chessTable[xTo][yTo].setIcon(bKnight);
                }
                _chessTable[xFrom][yFrom].setIcon(null);
                break;
        }

    }

    public boolean checkWhileChessingCell(int x, int y) {
        if (x > 0 && y > 0 && (_chessTable[x - 1][y - 1].getIcon() == bPawn
                || _chessTable[x - 1][y - 1].getIcon() == bKing
                || _chessTable[x - 1][y - 1].getIcon() == bQueen
                || _chessTable[x - 1][y - 1].getIcon() == bRook)) {
            return true;
        }
        if (x > 0 && (_chessTable[x - 1][y].getIcon() == bKing
                || _chessTable[x - 1][y].getIcon() == bQueen
                || _chessTable[x - 1][y].getIcon() == bRook)) {
            return true;
        }
        if (x > 0 && y < 7 && _chessTable[x - 1][y + 1].getIcon() == bPawn
                || _chessTable[x - 1][y + 1].getIcon() == bKing
                || _chessTable[x - 1][y + 1].getIcon() == bQueen
                || _chessTable[x - 1][y + 1].getIcon() == bRook) {
            return true;
        }
        if (y < 7 && (_chessTable[x][y + 1].getIcon() == bKing
                || _chessTable[x][y + 1].getIcon() == bQueen
                || _chessTable[x][y + 1].getIcon() == bRook)) {
            return true;
        }
        if (x < 7 && y < 7 && (_chessTable[x + 1][y + 1].getIcon() == bKing
                || _chessTable[x + 1][y + 1].getIcon() == bQueen
                || _chessTable[x + 1][y + 1].getIcon() == bRook)) {
            return true;
        }
        if (x < 7 && (_chessTable[x + 1][y].getIcon() == bKing
                || _chessTable[x + 1][y].getIcon() == bQueen
                || _chessTable[x + 1][y].getIcon() == bRook)) {
            return true;
        }
        if (x < 7 && y > 0 && (_chessTable[x + 1][y - 1].getIcon() == bKing
                || _chessTable[x + 1][y - 1].getIcon() == bQueen
                || _chessTable[x + 1][y - 1].getIcon() == bRook)) {
            return true;
        }
        if (x > 1 && y < 7 && (_chessTable[x - 2][y + 1].getIcon() == bKnight)) {
            return true;
        }
        if (x > 0 && y < 6 && (_chessTable[x - 1][y + 2].getIcon() == bKnight)) {
            return true;
        }
        if (x < 7 && y < 6 && (_chessTable[x + 1][y + 2].getIcon() == bKnight)) {
            return true;
        }
        if (x < 6 && y < 7 && (_chessTable[x + 2][y + 1].getIcon() == bKnight)) {
            return true;
        }
        if (x < 6 && y > 0 && (_chessTable[x + 2][y - 1].getIcon() == bKnight)) {
            return true;
        }
        if (x < 7 && y > 1 && (_chessTable[x + 1][y - 2].getIcon() == bKnight)) {
            return true;
        }
        if (x > 0 && y > 1 && (_chessTable[x - 1][y - 2].getIcon() == bKnight)) {
            return true;
        }
        if (x > 1 && y > 0 && (_chessTable[x - 2][y - 1].getIcon() == bKnight)) {
            return true;
        }
        boolean stopL = false;
        boolean stopC = false;
        boolean stopR = false;
        for (int i = x + 1; i < 8; i++) {
            if (stopL && (y - i + x >= 0) && (_chessTable[i][y - i + x].getIcon() == bBishop
                    || _chessTable[i][y - i + x].getIcon() == bQueen)) {
                return true;
            }
            stopL = (y - i + x >= 0) && _chessTable[i][y - i + x].getIcon() == null;
            if (stopC && (_chessTable[i][y].getIcon() == bRook
                    || _chessTable[i][y].getIcon() == bQueen)) {
                return true;
            }
            stopC = _chessTable[i][y].getIcon() == null;
            if (stopR && (y + i - x < 8) && (_chessTable[i][y + i - x].getIcon() == bBishop
                    || _chessTable[i][y + i - x].getIcon() == bQueen)) {
                return true;
            }
            stopR = (y + i - x < 8) && _chessTable[i][y + i - x].getIcon() == null;
            if (stopR && stopC && stopL) {
                break;
            }
        }
        stopL = false;
        stopC = false;
        stopR = false;
        for (int i = x - 1; i > 0; i--) {
            if (stopL && (y - i + x < 8) && (_chessTable[i][y - i + x].getIcon() == bBishop
                    || _chessTable[i][y - i + x].getIcon() == bQueen)) {
                return true;
            }
            stopL = (y - i + x < 8) && _chessTable[i][y - i + x].getIcon() == null;
            if (stopC && (_chessTable[i][y].getIcon() == bRook
                    || _chessTable[i][y].getIcon() == bQueen)) {
                return true;
            }
            stopC = _chessTable[i][y].getIcon() == null;
            if (stopR && (y + i - x >= 0) && (_chessTable[i][y + i - x].getIcon() == bBishop
                    || _chessTable[i][y + i - x].getIcon() == bQueen)) {
                return true;
            }
            stopR = (y + i - x >= 0) && _chessTable[i][y + i - x].getIcon() == null;
            if (stopR && stopC && stopL) {
                break;
            }
        }
        return false;
    }
}
